package sunyu.demo.storm.kafka;

import org.slf4j.Logger;
import sunyu.toolkit.core.LogKit;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author 孙宇
 */
public class ProtocolKit {

    private static final Logger logger = LogKit.getLogger();

    public static Map<String, Object> toMap(String msg) {
        Map<String, Object> m = new LinkedHashMap<>();
        Map<String, Object> m2 = new LinkedHashMap<>();
        //消息结构：消息前缀;序列号;终端ID;命令标识;参数明细。固定5列
        String[] args = msg.split("\\$");
        if (args.length != 5) {
            logger.error("内部协议格式错误，参数不够5个!");
            return null;
        }
        String[] params = args[4].split(",");
        m2.put("KAFKAMSG", msg);
        m.put("DID", args[2]);
        m.put("TIME", getParamValue(params, "TIME:"));
        if (args[0].equalsIgnoreCase("SUBMIT")) {
            if (args[3].equalsIgnoreCase("PACKET")) {
                m2.put("COMMANDNAME", "原始报文");

                submitPacket(m, m2, params);
            } else if (args[3].equalsIgnoreCase("LINKSTATUS")) {
                m2.put("COMMANDNAME", "链接状态通知");

                submitLinkstatus(m, m2, params);
            } else if (args[3].equalsIgnoreCase("TERMIN")) {
                m2.put("COMMANDNAME", "车辆登入消息");

                submitTermin(m, m2, params);
            } else if (args[3].equalsIgnoreCase("TERMOUT")) {
                m2.put("COMMANDNAME", "车辆登出消息");

                submitTermout(m, m2, params);
            } else if (args[3].equalsIgnoreCase("REALTIME")) {
                m2.put("COMMANDNAME", "实时信息上报");

                submitRealtime(m, m2, params);
            } else if (args[3].equalsIgnoreCase("HISTORY")) {
                m2.put("COMMANDNAME", "补发信息上报");

                submitRealtime(m, m2, params);
            } else if (args[3].equalsIgnoreCase("GETARG")) {
                m2.put("COMMANDNAME", "参数查询命令");

                submitGetarg(m, m2, params);
            } else if (args[3].equalsIgnoreCase("SETARG")) {
                m2.put("COMMANDNAME", "参数设置命令");

                submitSetarg(m, m2, params);
            } else if (args[3].equalsIgnoreCase("CONTROL")) {
                m2.put("COMMANDNAME", "终端控制");

                submitControl(m, m2, params);
            }
        } else if (args[0].equalsIgnoreCase("REPORT")) {
            if (args[3].equalsIgnoreCase("GETARG")) {
                m2.put("COMMANDNAME", "参数查询应答");

                reportGetarg(m, m2, params);
            } else if (args[3].equalsIgnoreCase("SETARG")) {
                m2.put("COMMANDNAME", "参数设置应答");

                reportSetarg(m, m2, params);
            } else if (args[3].equalsIgnoreCase("CONTROL")) {
                m2.put("COMMANDNAME", "控制应答");

                reportControl(m, m2, params);
            }
        }
        m.put("解释", m2);
        return m;
    }

    public static void reportControl(Map<String, Object> m, Map<String, Object> m2, String[] params) {
        m.put("RESULT", getParamValue(params, "RESULT:"));
        m2.put("RESULT应答结果0为成功，1为错误，2为超时", m.get("RESULT"));
    }

    public static void reportSetarg(Map<String, Object> m, Map<String, Object> m2, String[] params) {
        m.put("RESULT", getParamValue(params, "RESULT:"));
        m2.put("RESULT应答结果0为成功，1为错误，2为超时", m.get("RESULT"));
    }

    public static void submitControl(Map<String, Object> m, Map<String, Object> m2, String[] params) {
        m.put("KEY", getParamValue(params, "KEY:"));
        m2.put("KEY命令ID,见国标协议《控制命令定义》表", m.get("KEY"));

        m.put("VALUE", getParamValue(params, "VALUE:"));
        m2.put("VALUE命令参数,Base64(命令参数)，无参数时为空", m.get("VALUE"));
    }

    public static void submitGetarg(Map<String, Object> m, Map<String, Object> m2, String[] params) {
        m.put("ARGS", getParamValue(params, "ARGS:"));
        m2.put("ARGS查询ID列表(使用“|”分隔符，ID1|ID2|ID3)", m.get("ARGS"));
    }

    public static void submitTermout(Map<String, Object> m, Map<String, Object> m2, String[] params) {
        m.put("1101", getParamValue(params, "1101:"));
        m2.put("1101登出流水号", m.get("1101"));
    }

    public static void submitLinkstatus(Map<String, Object> m, Map<String, Object> m2, String[] params) {
        m.put("TYPE", getParamValue(params, "TYPE:"));
        if (m.get("TYPE").equals("1")) {
            m2.put("TYPE通知类型(1上线，2心跳，3离线)", "上线");
        } else if (m.get("TYPE").equals("2")) {
            m2.put("TYPE通知类型(1上线，2心跳，3离线)", "心跳");
        } else if (m.get("TYPE").equals("3")) {
            m2.put("TYPE通知类型(1上线，2心跳，3离线)", "离线");
        }
    }

    public static void reportGetarg(Map<String, Object> m, Map<String, Object> m2, String[] params) {
        m.put("RESULT", getParamValue(params, "RESULT:"));
        m2.put("RESULT应答结果,0为成功，1为错误，2为超时", m.get("RESULT"));

        m.put("1", getParamValue(params, "1:"));
        m2.put("1车载终端本地存储时间周期,有效值范围：0～60000（表示0ms～60000ms），最小计量单元：1ms", m.get("1"));

        m.put("2", getParamValue(params, "2:"));
        m2.put("2正常时，信息上报时间周期,有效值范围：1～600（表示1s～600s），最小计量单元：1s", m.get("2"));

        m.put("3", getParamValue(params, "3:"));
        m2.put("3出现报警时，信息上报时间周期,有效值范围：0～60000（表示0ms～60000ms），最小计量单元：1ms", m.get("3"));

        m.put("4", getParamValue(params, "4:"));
        m2.put("4远程服务与管理平台域名长度", m.get("4"));

        m.put("5", getParamValue(params, "5:"));
        m2.put("5远程服务与管理平台域名,Base64(域名)", m.get("5"));

        m.put("6", getParamValue(params, "6:"));
        m2.put("6远程服务与管理平台端口,有效值范围：0～65531，空表示无效", m.get("6"));

        m.put("7", getParamValue(params, "7:"));
        m2.put("7硬件版本,Base64(车载终端厂商自行定义)", m.get("7"));

        m.put("8", getParamValue(params, "8:"));
        m2.put("8固件版本,Base64(车载终端厂商自行定义)", m.get("8"));

        m.put("9", getParamValue(params, "9:"));
        m2.put("9车载终端心跳发送周期,有效值范围：1～240（表示1s～240s），最小计量单元：1s", m.get("9"));

        m.put("10", getParamValue(params, "10:"));
        m2.put("10终端应答超时时间,有效值范围：1～600（表示1s～600s），最小计量单元：1s", m.get("10"));

        m.put("11", getParamValue(params, "11:"));
        m2.put("11平台应答超时时间,有效值范围：1～600（表示1s～600s），最小计量单元：1s", m.get("11"));

        m.put("12", getParamValue(params, "12:"));
        m2.put("12连续三次登入失败后，到下一次登入的间隔时间,有效值范围：1～240，空表示无效", m.get("12"));

        m.put("13", getParamValue(params, "13:"));
        m2.put("13公共平台域名长度", m.get("13"));

        m.put("14", getParamValue(params, "14:"));
        m2.put("14公共平台域名,Base64(域名)", m.get("14"));

        m.put("15", getParamValue(params, "15:"));
        m2.put("15公共平台端口,有效值范围：0～65531，空表示无效", m.get("15"));

        m.put("16", getParamValue(params, "16:"));
        m2.put("16是否处于抽样监测中,1表示是，2表示否，空表示无效", m.get("16"));

        m.put("128", getParamValue(params, "128:"));
        m2.put("128车辆vin,Base64(车辆vin)", m.get("128"));

        m.put("129", getParamValue(params, "129:"));
        m2.put("129终端id,Base64(终端id)", m.get("129"));
    }

    public static void submitSetarg(Map<String, Object> m, Map<String, Object> m2, String[] params) {
        m.put("1", getParamValue(params, "1:"));
        m2.put("1车载终端本地存储时间周期,有效值范围：0～60000（表示0ms～60000ms），最小计量单元：1ms", m.get("1"));

        m.put("2", getParamValue(params, "2:"));
        m2.put("2正常时，信息上报时间周期,有效值范围：1～600（表示1s～600s），最小计量单元：1s", m.get("2"));

        m.put("3", getParamValue(params, "3:"));
        m2.put("3出现报警时，信息上报时间周期,有效值范围：0～60000（表示0ms～60000ms），最小计量单元：1ms", m.get("3"));

        m.put("4", getParamValue(params, "4:"));
        m2.put("4远程服务与管理平台域名长度", m.get("4"));

        m.put("5", getParamValue(params, "5:"));
        m2.put("5远程服务与管理平台域名,Base64(域名)", m.get("5"));

        m.put("6", getParamValue(params, "6:"));
        m2.put("6远程服务与管理平台端口,有效值范围：0～65531，空表示无效", m.get("6"));

        m.put("9", getParamValue(params, "9:"));
        m2.put("9车载终端心跳发送周期,有效值范围：1～240（表示1s～240s），最小计量单元：1s", m.get("9"));

        m.put("10", getParamValue(params, "10:"));
        m2.put("10终端应答超时时间,有效值范围：1～600（表示1s～600s），最小计量单元：1s", m.get("10"));

        m.put("11", getParamValue(params, "11:"));
        m2.put("11平台应答超时时间,有效值范围：1～600（表示1s～600s），最小计量单元：1s", m.get("11"));

        m.put("12", getParamValue(params, "12:"));
        m2.put("12连续三次登入失败后，到下一次登入的间隔时间,有效值范围：1～240，空表示无效", m.get("12"));

        m.put("13", getParamValue(params, "13:"));
        m2.put("13公共平台域名长度", m.get("13"));

        m.put("14", getParamValue(params, "14:"));
        m2.put("14公共平台域名,Base64(域名)", m.get("14"));

        m.put("15", getParamValue(params, "15:"));
        m2.put("15公共平台端口,有效值范围：0～65531，空表示无效", m.get("15"));

        m.put("128", getParamValue(params, "128:"));
        m2.put("128车辆vin,Base64(车辆vin)", m.get("128"));

        m.put("129", getParamValue(params, "129:"));
        m2.put("129终端id,Base64(终端id)", m.get("129"));
    }

    public static void submitRealtime(Map<String, Object> m, Map<String, Object> m2, String[] params) {
        m.put("2001", getParamValue(params, "2001:"));
        m2.put("2001单体电池总数，有效值范围：1～65531", m.get("2001"));

        m.put("2002", getParamValue(params, "2002:"));
        m2.put("2002电压储能子系统总数，有效值范围：1～250", m.get("2002"));

        m.put("2003", getParamValue(params, "2003:"));
        m2.put("2003电压值列表，列表使用“|”分隔符，单位：0.001V，base64(电压值数组1)|base64(电压值数组2)", m.get("2003"));

        m.put("2101", getParamValue(params, "2101:"));
        m2.put("2101温度探针总数，有效值范围：0～65531", m.get("2101"));

        m.put("2102", getParamValue(params, "2102:"));
        m2.put("2102温度储能子系统总数，有效值范围：1～252", m.get("2102"));

        m.put("2103", getParamValue(params, "2103:"));
        m2.put("2103温度值列表，列表使用“|”分隔符，偏移量40℃，单位：1℃，base64(温度值数组1)|base64(温度值数组2)", m.get("2103"));

        m.put("2201", getParamValue(params, "2201:"));
        m2.put("2201车辆状态，1：车辆启动状态；2：熄火；3：其他状态", m.get("2201"));

        m.put("2202", getParamValue(params, "2202:"));
        m2.put("2202充电状态，1：停车充电；2：行驶充电；3：未充电状态；4：充电完成", m.get("2202"));

        m.put("2203", getParamValue(params, "2203:"));
        m2.put("2203运行模式，1: 纯电；2：混动；3：燃油", m.get("2203"));

        m.put("2204", getParamValue(params, "2204:"));
        m2.put("2204车速,单位：1km/h", m.get("2204"));

        m.put("2205", getParamValue(params, "2205:"));
        m2.put("2205里程,单位：1km", m.get("2205"));

        m.put("2206", getParamValue(params, "2206:"));
        m2.put("2206总电压,单位：1V", m.get("2206"));

        m.put("2207", getParamValue(params, "2207:"));
        m2.put("2207总电流,单位：1A", m.get("2207"));

        m.put("2208", getParamValue(params, "2208:"));
        m2.put("2208SOC,单位：1%", m.get("2208"));

        m.put("2209", getParamValue(params, "2209:"));
        m2.put("2209DC-DC状态,1：工作；2：断开", m.get("2209"));

        m.put("2210", getParamValue(params, "2210:"));
        m2.put("2210档位,见终端接入协议附录A.1", m.get("2210"));

        m.put("2211", getParamValue(params, "2211:"));
        m2.put("2211绝缘电阻,单位：1KΩ", m.get("2211"));

        m.put("2212", getParamValue(params, "2212:"));
        m2.put("2212加速踏板行程值,单位：1%", m.get("2212"));

        m.put("2213", getParamValue(params, "2213:"));
        m2.put("2213制动踏板行程值,单位：1%", m.get("2213"));

        m.put("2301", getParamValue(params, "2301:"));
        m2.put("2301驱动电机个数,有效值1～253", m.get("2301"));

        m.put("2302", getParamValue(params, "2302:"));
        m2.put("2302驱动电机序号,列表使用“|”分隔符", m.get("2302"));

        m.put("2303", getParamValue(params, "2303:"));
        m2.put("2303驱动电机状态,列表使用“|”分隔符，1：耗电；2：发电；3：关闭状态；4：准备状态", m.get("2303"));

        m.put("2304", getParamValue(params, "2304:"));
        m2.put("2304电机控制器温度,列表使用“|”分隔符，单位：1℃", m.get("2304"));

        m.put("2305", getParamValue(params, "2305:"));
        m2.put("2305电机转速,列表使用“|”分隔符，单位：1r/min", m.get("2305"));

        m.put("2306", getParamValue(params, "2306:"));
        m2.put("2306电机转矩,列表使用“|”分隔符，单位：1N*m", m.get("2306"));

        m.put("2307", getParamValue(params, "2307:"));
        m2.put("2307电机温度,列表使用“|”分隔符，单位：1℃", m.get("2307"));

        m.put("2308", getParamValue(params, "2308:"));
        m2.put("2308电机控制器电压,列表使用“|”分隔符，单位：1V", m.get("2308"));

        m.put("2309", getParamValue(params, "2309:"));
        m2.put("2309电机控制器电流,列表使用“|”分隔符，单位：1A", m.get("2309"));

        m.put("2401", getParamValue(params, "2401:"));
        m2.put("2401燃料电池电压,单位：1V", m.get("2401"));

        m.put("2402", getParamValue(params, "2402:"));
        m2.put("2402燃料电池电流,单位：1A", m.get("2402"));

        m.put("2403", getParamValue(params, "2403:"));
        m2.put("2403燃料消耗率,单位：1kg/100km", m.get("2403"));

        m.put("2404", getParamValue(params, "2404:"));
        m2.put("2404燃料电池温度探针总数,有效值范围：0～65531", m.get("2404"));

        m.put("2405", getParamValue(params, "2405:"));
        m2.put("2405探针温度值,列表使用“|”分隔符，单位：1℃", m.get("2405"));

        m.put("2406", getParamValue(params, "2406:"));
        m2.put("2406氢系统中最高温度，单位：1℃", m.get("2406"));

        m.put("2407", getParamValue(params, "2407:"));
        m2.put("2407氢系统中最高温度探针代号，有效值范围：1～252", m.get("2407"));

        m.put("2408", getParamValue(params, "2408:"));
        m2.put("2408氢气最高浓度，单位：1ppm", m.get("2408"));

        m.put("2409", getParamValue(params, "2409:"));
        m2.put("2409氢气最高浓度传感器代号，有效值范围：1～252", m.get("2409"));

        m.put("2410", getParamValue(params, "2410:"));
        m2.put("2410氢气最高压力，单位：1MPa", m.get("2410"));

        m.put("2411", getParamValue(params, "2411:"));
        m2.put("2411氢气最高压力传感器代号，有效值范围：1～252", m.get("2411"));

        m.put("2412", getParamValue(params, "2412:"));
        m2.put("2412高压DC/DC状态，1：工作；2：断开", m.get("2412"));

        m.put("2501", getParamValue(params, "2501:"));
        m2.put("2501发动机状态，1：启动状态；2：关闭状态", m.get("2501"));

        m.put("2502", getParamValue(params, "2502:"));
        m2.put("2502曲轴转速，单位：1rpm", m.get("2502"));

        m.put("2503", getParamValue(params, "2503:"));
        m2.put("2503燃料消耗率，单位：1L/100km", m.get("2503"));

        m.put("2601", getParamValue(params, "2601:"));
        m2.put("2601定位状态，见终端接入协议表《状态位定义》", m.get("2601"));

        m.put("2602", getParamValue(params, "2602:"));
        m2.put("2602经度，以度为单位乘以10的6次方，精确到百万分之一度", m.get("2602"));

        m.put("2603", getParamValue(params, "2603:"));
        m2.put("2603纬度，以度为单位乘以10的6次方，精确到百万分之一度", m.get("2603"));

        m.put("2701", getParamValue(params, "2701:"));
        m2.put("2701最高电压动力蓄电池单体所在电池包序号", m.get("2701"));

        m.put("2702", getParamValue(params, "2702:"));
        m2.put("2702最高电压单体蓄电池序号", m.get("2702"));

        m.put("2703", getParamValue(params, "2703:"));
        m2.put("2703电池单体电压最高值，单位：1V", m.get("2703"));

        m.put("2704", getParamValue(params, "2704:"));
        m2.put("2704最低电压动力蓄电池包序号", m.get("2704"));

        m.put("2705", getParamValue(params, "2705:"));
        m2.put("2705最低电压单体蓄电池序号", m.get("2705"));

        m.put("2706", getParamValue(params, "2706:"));
        m2.put("2706电池单体电压最低值，单位：1V", m.get("2706"));

        m.put("2707", getParamValue(params, "2707:"));
        m2.put("2707最高温度动力蓄电池包序号", m.get("2707"));

        m.put("2708", getParamValue(params, "2708:"));
        m2.put("2708最高温度探针序号", m.get("2708"));

        m.put("2709", getParamValue(params, "2709:"));
        m2.put("2709最高温度值，单位：1℃", m.get("2709"));

        m.put("2710", getParamValue(params, "2710:"));
        m2.put("2710最低温度动力蓄电池包序号", m.get("2710"));

        m.put("2711", getParamValue(params, "2711:"));
        m2.put("2711最低温度探针序号", m.get("2711"));

        m.put("2712", getParamValue(params, "2712:"));
        m2.put("2712最低温度值，单位：1℃", m.get("2712"));

        m.put("2801", getParamValue(params, "2801:"));
        m2.put("2801最高报警等级，为当前发生的故障中的最高等级值", m.get("2801"));

        m.put("2802", getParamValue(params, "2802:"));
        m2.put("2802通用报警标志，通用报警标志位定义见表18", m.get("2802"));

        m.put("2803", getParamValue(params, "2803:"));
        m2.put("2803可充电储能装置故障总数", m.get("2803"));

        m.put("2804", getParamValue(params, "2804:"));
        m2.put("2804可充电储能装置故障代码列表,列表使用“|”分隔符", m.get("2804"));

        m.put("2805", getParamValue(params, "2805:"));
        m2.put("2805驱动电机故障总数", m.get("2805"));

        m.put("2806", getParamValue(params, "2806:"));
        m2.put("2806驱动电机故障代码列表,列表使用“|”分隔符", m.get("2806"));

        m.put("2807", getParamValue(params, "2807:"));
        m2.put("2807发动机故障总数", m.get("2807"));

        m.put("2808", getParamValue(params, "2808:"));
        m2.put("2808发动机故障列表,列表使用“|”分隔符", m.get("2808"));

        m.put("2809", getParamValue(params, "2809:"));
        m2.put("2809其他故障总数", m.get("2809"));

        m.put("2810", getParamValue(params, "2810:"));
        m2.put("2810其他故障代码列表,列表使用“|”分隔符", m.get("2810"));

        m.put("2901", getParamValue(params, "2901:"));
        m2.put("2901自定义类型编码列表,列表使用“|”分隔符", m.get("2901"));

        m.put("2902", getParamValue(params, "2902:"));
        m2.put("2902自定义类型数据列表,Base64(数据1)|Base64(数据2)|Base64(数据3)", m.get("2902"));
    }

    public static void submitTermin(Map<String, Object> m, Map<String, Object> m2, String[] params) {
        m.put("1001", getParamValue(params, "1001:"));
        m2.put("1001登入流水号", m.get("1001"));

        m.put("1002", getParamValue(params, "1002:"));
        m2.put("1002Bsse64ICCID", m.get("1002"));

        m.put("1003", getParamValue(params, "1003:"));
        m2.put("1003可充电储能子系统数", m.get("1003"));

        m.put("1004", getParamValue(params, "1004:"));
        m2.put("1004可充电储能系统编码长度", m.get("1004"));

        m.put("1005", getParamValue(params, "1005:"));
        m2.put("1005可充电储能系统编码，Base64(编码1)|Base64(编码2)", m.get("1005"));

        m.put("RESULT", getParamValue(params, "RESULT:"));
        m2.put("RESULT登入结果", m.get("RESULT"));
    }

    public static void submitPacket(Map<String, Object> m, Map<String, Object> m2, String[] params) {
        m.put("1", getParamValue(params, "1:"));
        m2.put("1消息类型，见车载终端协议《命令标识定义》表", m.get("1"));

        m.put("2", getParamValue(params, "2:"));
        m2.put("2原始报文，报文字节数组经过base64编码", m.get("2"));

        m.put("3", getParamValue(params, "3:"));
        m2.put("3校验状态", m.get("3"));
    }

    private static String getParam(String[] params, String regx) {
        for (String param : params) {
            if (param.indexOf(regx) > -1) {
                return param;
            }
        }
        return null;
    }

    private static String getParamValue(String param) {
        String[] ps = param.split(":");
        if (ps.length == 2) {
            String v = ps[1];
            if (v.lastIndexOf("}") == 1) {//袁春青写错了，多了一个，所以要去掉
                v = v.substring(0, v.length() - 1);
            }
            return v;
        }
        return "";
    }

    private static String getParamValue(String[] params, String regx) {
        String param = getParam(params, regx);
        if (param != null) {
            return getParamValue(param);
        } else {
            return "";
        }
    }

}
